package com.gollum.system.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.gollum.common.context.PageContextHolder;
import com.gollum.common.domain.response.TableSupport;
import com.gollum.common.enums.SystemStatus;
import com.gollum.common.utils.BeanUtils;
import com.gollum.common.utils.StringUtils;
import com.gollum.jpa.common.Specifications;
import com.gollum.jpa.domain.Page;
import com.gollum.jpa.service.JpaServerImpl;
import com.gollum.jpa.util.LambdaUtils;
import com.gollum.system.domain.dao.SysDeptDao;
import com.gollum.system.domain.dao.SysUserDao;
import com.gollum.system.domain.model.SysDept;
import com.gollum.system.domain.model.SysLogininfor;
import com.gollum.system.domain.model.SysRole;
import com.gollum.system.domain.model.SysUser;
import com.gollum.system.domain.request.SysUserRequest;
import com.gollum.system.domain.response.SysLogininforResponse;
import com.gollum.system.domain.response.SysUserResponse;
import com.gollum.system.service.SysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.persistence.criteria.*;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 系统用户service实现
 *
 * @author Herther
 * @version 1.0.0
 * @createTime 2022年08月25日 21:55:00
 */
@Service
public class SysUserServiceImpl extends JpaServerImpl<SysUser, Long> implements SysUserService {

    @Autowired
    private SysUserDao sysUserDao;

    @Autowired
    protected SysDeptDao sysDeptDao;

    /**
     * 功能描述:
     *
     * @param parentId 父ID
     * @return 查询底下的所有子集
     * @auther: Herther
     * @since 1.0.0
     * @date: 2022/10/13 21:37
     */
    private List<Long> getDeptId(Long id){
        Specification<SysDept> params = new Specification<SysDept>() {
            @Override
            public Predicate toPredicate(Root<SysDept> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) {
                List<Predicate> list = CollUtil.newArrayList();
                list.add(cb.equal(root.get(LambdaUtils.getFieldName(SysDept::getStatus)), SystemStatus.NORMAL.getValue()));
                Expression<Long> findInSetFun =
                        cb.function("FIND_IN_SET", Long.class, cb.literal(id), root.get(LambdaUtils.getFieldName(SysDept::getAncestors)));
                list.add(cb.gt(findInSetFun,0));
                return cb.and(list.toArray(new Predicate[list.size()]));
            }
        };

        List<SysDept> list = sysDeptDao.findAll(params);
        return list.stream()
                .map(SysDept::getId)
                .collect(Collectors.toList());
    }




    @Override
    public List<SysUser> findAllTest() {
        return this.findAll();
    }

    @Override
    public SysUser getUserByUsername(String username) {
        SysUser byUsername = sysUserDao.findByUsername(username);
        return byUsername;
    }
    @Override
    public TableSupport<SysUserResponse> listPage(SysUserRequest params) {
        //tips: 需要controller构建分页才能拿到PageContextHolder 才能拿到分页的参数
        Page<SysUser> page = PageContextHolder.get().toPage();
        //查询
        page = findAllWithPage(page,getParams(params));
        return TableSupport.toTableResponse(page, BeanUtils.copyToList(page.getRecords(), SysUserResponse.class));
    }


    /**
     * 构建查询参数
     *
     * @param params 查询参数构建Jpa标准
     * @return Specification
     * @auther: Herther
     * @since 1.0.0
     * @date: 2022/10/13 21:54
     */
    public Specification<SysUser> getParams(SysUserRequest params){
        List<Long> deptIds = CollUtil.newArrayList();
        if (StringUtils.isNotNull(params.getDeptId())  ||  params.getDeptId() != 0L ){
             deptIds = getDeptId(params.getDeptId());
        }
        //or参数
        Specification<SysUser> orParams = Specifications.<SysUser>or()
                .eq(StringUtils.isNotNull(params.getDeptId())  ||  params.getDeptId() != 0L,SysUser::getDeptId,params.getDeptId()).build();
        //and 参数
        Specification<SysUser> andParams = Specifications.<SysUser>and()
                //.in(!CollectionUtils.isEmpty(deptId),SysUser::getDeptId, getDeptId(params.getDeptId()))
                .in(!CollectionUtils.isEmpty(deptIds),SysUser::getDeptId,deptIds)
                .eq(StringUtils.isNotEmpty(params.getUsername()),
                        SysUser::getUsername, params.getUsername())

                .eq(StringUtils.isNotEmpty(params.getNickName()),
                        SysUser::getNickName, params.getNickName())

                .eq(StringUtils.isNotEmpty(params.getEmail()),
                        SysUser::getEmail, params.getEmail())

                .eq(StringUtils.isNotEmpty(params.getMobile()),
                        SysUser::getMobile, params.getMobile())

                .eq(StringUtils.isNotEmpty(params.getSex()),
                        SysUser::getSex, params.getSex())

                .eq(StringUtils.isNotEmpty(params.getStatus()),
                        SysUser::getStatus, params.getStatus())

                .eq(StringUtils.isNotEmpty(params.getUserType()),
                        SysUser::getUserType, params.getUserType())

                .eq(StringUtils.isNotEmpty(params.getRealName()),
                        SysUser::getRealName, params.getRealName())

                .between(getBetweenCondition(params.getBeginTime()
                                , params.getEndTime())
                        , SysUser::getCreateTime
                        , params.getBeginTime(), params.getEndTime())
                .build().or(orParams);

        return andParams;
    }
}
